#include <tinx/printk.h>
#include <tinx/task.h>
#include <tinx/device.h>
#include <tinx/debug.h>
#include <tinx/string.h>
#include <tinx/syscall.h>
#include <tinx/assert.h>

#define LOGK(str, args...) DEBUGK(str, ##args)

handler_t syscall_table[SYSCALL_NUM];

void syscall_check(u32 nr)
{
    if (nr >= SYSCALL_NUM || !syscall_table[nr])
    {
        task_t *task = running_task();
        intr_frame_t *iframe = (intr_frame_t *)((u32)task + 0x1000 - sizeof(intr_frame_t));
        panic("task %s ERROR syscall %d eip 0x%p", task->name, nr, iframe->eip);
    }
    if (nr == 158)
        return;
    LOGK("syscall nr %d\n", nr);
}

extern int sys_test();
extern time_t sys_time();

extern fd_t sys_open();
extern fd_t sys_creat();
extern int sys_close();

extern int sys_read();
extern int sys_write();
extern int sys_writev();
extern int sys_ioctl();
extern int sys_lseek();

extern int sys_getdents();
extern int sys_readdir();

extern int sys_mkdir();
extern int sys_mkdirat();
extern int sys_rmdir();

extern int sys_link();
extern int sys_unlink();

extern int sys_stat();
extern int sys_fstat();
extern int sys_statx();

extern int sys_old_stat();
extern int sys_old_fstat();

extern int sys_rename();

extern int sys_readlink();
extern int sys_symlink();

extern fd_t sys_dup();
extern fd_t sys_dup2();

extern int sys_fcntl();
extern int sys_fcntl64();

extern int sys_chdir();
extern int sys_chroot();

extern int sys_mknod();

extern int sys_pipe();

extern int sys_mount();
extern int sys_umount();

extern int sys_reboot();
extern int sys_shutdown();

extern int sys_mmap();
extern int sys_mmap2();
extern int sys_munmap();
extern int sys_mprotect();
extern int sys_brk();

extern int sys_set_thread_area();
extern int sys_set_tid_address();

extern int sys_clock_gettime();
extern int sys_clock_gettime64();

void syscall_init()
{
    memset(syscall_table, 0, sizeof(syscall_table));

    syscall_table[SYS_NR_TEST] = sys_test;

    syscall_table[SYS_NR_WRITE] = sys_write;
    syscall_table[SYS_NR_WRITEV] = sys_writev;
    syscall_table[SYS_NR_READ] = sys_read;
    syscall_table[SYS_NR_IOCTL] = sys_ioctl;

    syscall_table[SYS_NR_READDIR] = sys_readdir;
    syscall_table[SYS_NR_GETDENTS] = sys_getdents;

    syscall_table[SYS_NR_LSEEK] = sys_lseek;

    syscall_table[SYS_NR_SYMLINK] = sys_symlink;
    syscall_table[SYS_NR_READLINK] = sys_readlink,

    syscall_table[SYS_NR_MKDIR] = sys_mkdir;
    syscall_table[SYS_NR_MKDIRAT] = sys_mkdirat;
    syscall_table[SYS_NR_RMDIR] = sys_rmdir;

    syscall_table[SYS_NR_LINK] = sys_link;
    syscall_table[SYS_NR_UNLINK] = sys_unlink;

    syscall_table[SYS_NR_OPEN] = sys_open;
    syscall_table[SYS_NR_CREAT] = sys_creat;
    syscall_table[SYS_NR_CLOSE] = sys_close;

    syscall_table[SYS_NR_CHDIR] = sys_chdir;
    syscall_table[SYS_NR_CHROOT] = sys_chroot;

    syscall_table[SYS_NR_MKNOD] = sys_mknod;

    syscall_table[SYS_NR_RENAME] = sys_rename;

    syscall_table[SYS_NR_PIPE] = sys_pipe;

    syscall_table[SYS_NR_STAT] = sys_stat;
    syscall_table[SYS_NR_FSTAT] = sys_fstat;
    syscall_table[SYS_NR_STATX] = sys_statx;

    syscall_table[SYS_NR_OLD_STAT] = sys_old_stat;
    syscall_table[SYS_NR_OLD_FSTAT] = sys_old_fstat;

    syscall_table[SYS_NR_DUP] = sys_dup;
    syscall_table[SYS_NR_DUP2] = sys_dup2;

    syscall_table[SYS_NR_FCNTL] = sys_fcntl;
    syscall_table[SYS_NR_FCNTL64] = sys_fcntl64;

    syscall_table[SYS_NR_MOUNT] = sys_mount;
    syscall_table[SYS_NR_UMOUNT] = sys_umount;

    syscall_table[SYS_NR_EXIT] = task_exit;
    syscall_table[SYS_NR_FORK] = task_fork;
    syscall_table[SYS_NR_WAITPID] = task_waitpid;
    syscall_table[SYS_NR_EXECVE] = sys_execve;
    syscall_table[SYS_NR_YIELD] = task_yield;

    syscall_table[SYS_NR_TIME] = sys_time;

    syscall_table[SYS_NR_BRK] = sys_brk;

    syscall_table[SYS_NR_SHUTDOWN] = sys_shutdown;
    syscall_table[SYS_NR_REBOOT] = sys_reboot;

    syscall_table[SYS_NR_GETPID] = task_getpid;
    syscall_table[SYS_NR_GETPPID] = task_getppid;
    syscall_table[SYS_NR_GETUID] = task_getuid;

    syscall_table[SYS_NR_MMAP] = sys_mmap;
    syscall_table[SYS_NR_MMAP2] = sys_mmap2;
    syscall_table[SYS_NR_MUNMAP] = sys_munmap;
    syscall_table[SYS_NR_MPROTECT] = sys_mprotect;

    syscall_table[SYS_NR_SET_THREAD_AREA] = sys_set_thread_area;
    syscall_table[SYS_NR_SET_TID_ADDRESS] = sys_set_tid_address;

    syscall_table[SYS_NR_CLOCK_GETTIME] = sys_clock_gettime;
    syscall_table[SYS_NR_CLOCK_GETTIME64] = sys_clock_gettime64;
}